Skip to content

ci: require a closing magic word for the Linear link - #222

Merged
jacderida merged 1 commit into
WithAutonomi:mainfrom
jacderida:chrisoneil/v2-1161-make-the-prs-linear-link-a-real-link-require-a-magic-word-in
Sep 4, 2026
Merged

ci: require a closing magic word for the Linear link#222
jacderida merged 1 commit into
WithAutonomi:mainfrom
jacderida:chrisoneil/v2-1161-make-the-prs-linear-link-a-real-link-require-a-magic-word-in

Conversation

@jacderida

@jacderida jacderida commented Sep 4, 2026

Copy link
Copy Markdown
Member

Linear issue

Closes V2-1161

Risk tier

  • T0 — docs / tooling / CI / pure UX-output. Repo CI only.

Compatibility

  • Wire: none
  • Storage: none
  • API: none

Semver impact

  • fix

Test evidence

python3 .github/scripts/test_check_pr.py52/52 cases pass, in this repo and
in all six (the self-test job runs the same matrix). The matrix grew from 17 to 52
cases, asserting: one case per closing magic word Linear documents, in the tense an
author would actually write (Closed, Fixed, Resolving, Implemented, …); the
Closes <linear.app issue URL> form; lower-cased input; the linear issue phrase;
the linking-only families (ref, part of, towards, relates to) rejected, since
they attach a PR without driving the Merged transition; word-boundary cases
(prefix/fixture must not match); a magic word with no key; a magic word separated
from its key by a blank line; and bare key or bare issue URL in the body — the last of
which used to pass and now fails, which is the point of the change.

The accepted set is taken verbatim from https://linear.app/docs/github and restated
independently in the test matrix, so the matrix is an assertion about the documented
behaviour rather than a restatement of the implementation.

This PR is its own end-to-end test: it carries the closing form in the body, and the
pull_request event runs the version of check_pr.py from this branch.

New dependency

none

ADR

n/a

Mitigation / rollback

Revert the commit. The check is a CI gate with no runtime surface; reverting restores
the previous linear-link behaviour immediately.

@dirvine dirvine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One blocking issue: this checker does not match Linear’s documented closing syntax. Linear supports close/closes/closed/closing, fix/fixes/fixed/fixing, resolve/resolves/resolved/resolving, complete/completes/completed/completing, implement/implements/implemented/implementing, and linear issue; MAGIC_WORDS accepts only five of those.

For example, Fixed V2-1161 links and closes the issue in Linear, but I reproduced that it exits 1 here. Because this is merge-blocking CI, it would reject valid Linear-linked PRs, while the new comments also incorrectly say these five are the closing words Linear recognises. Please expand MAGIC_WORDS and the tests to cover Linear’s official closing set.

Official reference: https://linear.app/docs/github

A bare `V2-123` in a PR description does not link the PR to the issue —
Linear ignores it — so a PR could pass the `linear-link` check while never
appearing on the issue and never driving it to Merged when it lands on
`main`. ant-node WithAutonomi#216 is the concrete case: it carried `V2-1033` under the
Linear heading, had no identifier in its branch name, and had to be
attached to the issue by hand.

The `linear-link` check now requires one of Linear's closing magic words
followed by the issue key in the PR body. The accepted set is taken
verbatim from https://linear.app/docs/github — close / fix / resolve /
complete / implement in every tense (`-s`, `-d`, `-ing`) plus the phrase
`linear issue`, case-insensitive, with either the key or a linear.app
issue URL. Linear's linking-only families (`ref`, `part of`, `towards`,
`relates to`) attach a PR without driving the Merged transition, so they
are deliberately not accepted. An identifier in the branch name or the PR
title remains an accepted alternative, since both also link the PR.

The magic word and the key must sit on the same line, so a paragraph that
merely ends in "...closes." cannot pair up with a bare key further down
the body, and the template's own `## Linear issue` heading cannot pair up
with a bare key on the line beneath it.

`pr-template` applies the same rule to the `## Linear issue` section, and
the template comment and CLAUDE.md now ask for the closing form and say
why the bare and linking-only forms do not work. The self-test matrix
grows from 17 to 52 cases: one per documented closing word, the URL form,
case-insensitivity, the linking-only rejections, word-boundary cases, and
the bare-reference rejections.

Closes V2-1161

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WN8hjL7E8qcCxJBgT9vFt6
@jacderida
jacderida force-pushed the chrisoneil/v2-1161-make-the-prs-linear-link-a-real-link-require-a-magic-word-in branch from 2611d7c to 0c47709 Compare September 4, 2026 21:45
@jacderida

Copy link
Copy Markdown
Member Author

You're right, and I've fixed it — amended and force-pushed.

I checked the claim against https://linear.app/docs/github rather than taking it on trust, and the docs confirm it. MAGIC_WORDS is now the documented closing set, verbatim, all 21 entries:

close, closes, closed, closing
fix, fixes, fixed, fixing
resolve, resolves, resolved, resolving
complete, completes, completed, completing
implement, implements, implemented, implementing
linear issue

Your repro now passes:

$ PR_BODY="Fixed V2-1161" PR_BRANCH=x python3 .github/scripts/check_pr.py linear
✅ Linear link found in the PR body: Fixed V2-1161
(exit 0)

Alternatives are sorted longest-first when the pattern is built, so close cannot shadow closes.

What I did not add, deliberately: the linking-only families the same docs page lists — ref / refs / references, part of / contributes to / toward / towards, and relates to / related to. Those attach the PR but do not drive the status transition on merge, and this issue (V2-1161) exists specifically to make the Merged automation fire. Accepting them would leave the original bug in place under a different spelling. They now have explicit rejection cases in the matrix, and the failure message calls them out by name so nobody hits that wall without an explanation.

On the incorrect comments: also fixed. check_pr.py, PULL_REQUEST_TEMPLATE.md and CLAUDE.md no longer claim five words are the set — they describe the five stems in any tense plus the linear issue phrase, cite the docs page, and state why the linking-only words are excluded.

Tests: the matrix went 30 → 52 cases. It generates one case per closing word from its own tuple, restated independently of check_pr.py so it asserts the documented behaviour rather than mirroring the implementation, plus rejection cases for each linking-only family and for word-boundary near-misses (prefix V2-1161, fixture V2-1161). 52/52 pass in all six repos.

The same amended commit is on all six train repos.

@dirvine dirvine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up review: the full documented Linear closing-word set is now covered, including the previously rejected forms. The expanded local test suite passes 52/52. Approved.

@jacderida
jacderida merged commit a04cf15 into WithAutonomi:main Sep 4, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants